package com.ivan.toolkit.common;

public class DataWrap {
	
	private byte[] data;
	
	private int offset;
	
	private int length;
	
	public DataWrap() {
	}
	
	public void setData(byte[] data, int offset, int length) throws Exception {
		if(data == null || offset < 0 || (offset + length) > data.length) {
			throw new RuntimeException("DataWrap.setData() : invalid parameter.");
		}
		this.data = data;
		this.offset = offset;
		this.length = length;
	}
	
	public void setData(byte[] data) throws Exception {
		setData(data, 0, data.length);
	}
	
	public int getOffset() {
		return this.offset;
	}
	
	public int getLength() {
		return this.length;
	}
	
	private void validate(int o, int l) throws Exception {
		if(data == null || o < 0 || (o + l) > data.length) {
			throw new RuntimeException("DataWrap : out of array.");
		}
	}
	
	private int idx(int index) {
		return offset + index;
	}
	
	public DataWrap subWrap(int index, int len) throws Exception {
		DataWrap sub = new DataWrap();
		sub.setData(data, idx(index), len);
		return sub;
	}
	
	public void setByte(int index, int value) throws Exception {
		validate(idx(index), 1);
		data[idx(index)] = (byte)(value & 0xFF);
	}
	
	public int getByte(int index) throws Exception {
		validate(idx(index), 1);
		return data[idx(index)] & 0xFF;
	}
	
	public void setShort(int index, int value, boolean bigEndian) throws Exception {
		//validate(idx(index), 2);
		int v1 = (value & 0xFF00) >> 8;
		int v2 = value & 0xFF;
		if(bigEndian) {
			this.setByte(index, v1);
			this.setByte(index + 1, v2);
		} else {
			this.setByte(index, v2);
			this.setByte(index + 1, v1);
		}
	}
	
	public int getShort(int index, boolean bigEndian) throws Exception {
		//validate(index, 2);
		int v1 = getByte(index);
		int v2 = getByte(index + 1);
		if(bigEndian) {
			return (int)((v1 << 8) + v2);
		} else {
			return (int)((v2 << 8) + v1);
		}
	}
	
	public void setInteger(int index, int value, boolean bigEndian) throws Exception {
		//validate(index, 4);
		int v1 = (value & 0xFFFF0000) >> 16;
		int v2 = value & 0xFFFF;
		if(bigEndian) {
			this.setShort(index, v1, bigEndian);
			this.setShort(index + 2, v2, bigEndian);
		} else {
			this.setShort(index, v2, bigEndian);
			this.setShort(index + 2, v1, bigEndian);
		}
	}
	
	public int getInteger(int index, boolean bigEndian) throws Exception {
		//validate(index, 4);
		int v1 = getShort(index + 2, bigEndian);
		int v2 = getShort(index, bigEndian);
		if(bigEndian) {
			return (int)((v1 << 16) + v2);
		} else {
			return (int)((v2 << 16) + v1);
		}
	}
	
}
